unit BInt;

interface
{const
  numlen = 102;}
uses
  BigInt, Math;
type
  BigInteger = class
  private
    a: number;//array [1..numlen] of byte;
    s: ShortInt;
    l: Byte;
  public
    constructor Create(num: LongInt); overload;
    constructor Create(abs: number; sign: ShortInt); overload;
    function GetAbsoluteValue: number;
    function GetSign: ShortInt;
    function Copy: BigInteger;
    procedure InvertSign;
    function Add(b: BigInteger): BigInteger;
    function SubStract(b: BigInteger): BigInteger;
    function Sqrt: BigInteger;
    function SqrtRough: BigInteger;
    function SqrtCeil: BigInteger;
    function SqrtFloor: BigInteger;
    function toExt: Extended;
    procedure BigInc;
    procedure BigDec;
    procedure readFromFile(var f: TextFile);
    procedure writeToFile(var f: TextFile);
    function getLen: Byte;

  end;

implementation

{ BigInteger }

function BigInteger.Add(b: BigInteger): BigInteger;
var
  x: number;
  bs: ShortInt;
begin
  bs := b.GetSign();
  if bs = 0 then begin
    Result := self;
    Exit;
  end;

  x := b.GetAbsoluteValue;
  if s = 0 then begin
    a := x;
    s := bs;
    Result := self;
    Exit;
  end;

  if s * bs > 0 then begin
    BigInt.add(a, x);
    s := 1;
  end else if (cmp(a, x) = 0) then begin
    s := 0;
    set0(a);
  end else if (cmp(a, x) = 1) then
    BigInt.subStract(a, x)
  else begin
    BigInt.subStract(x, a);
    a := x;
    InvertSign;
  end;
  Result := self;
end;

function BigInteger.Copy: BigInteger;
begin
  Result := BigInteger.Create(a, s)
end;

constructor BigInteger.Create(num: Integer);
begin
  if (num = 0) then
    s := 0
  else
    if (num > 0) then
      s := 1
    else
      s := -1;
  setn(a, abs(num));
end;

constructor BigInteger.Create(abs: number; sign: ShortInt);
begin
  a := abs;
  s := sign;
end;

procedure BigInteger.BigDec;
begin
  SubStract(BigInteger.Create(1));
end;

function BigInteger.GetAbsoluteValue: number;
begin
  Result := a;
end;

function BigInteger.getLen: Byte;
begin
  Result := len(a);
end;

function BigInteger.GetSign: ShortInt;
begin
  Result := s;
end;

procedure BigInteger.BigInc;
begin
  Add(BigInteger.Create(1));
end;

procedure BigInteger.InvertSign;
begin
  s := -s;
end;

procedure BigInteger.readFromFile(var f: TextFile);
var
  s: String;
  i, j: Byte;
  e: Integer;
begin
  Readln(f, s);
  set0(a);
  l := 0;
  for i := 1 to Length(s) do begin
    Val(s[i], j, E);
    if (E = 0) then begin
      a[i] := j;
      Inc(l);
    end
    else
      break;
  end;
end;

function BigInteger.SqrtRough: BigInteger;
var
  l, n: Byte;
  x: number;
begin
  l := len(a);
  n := Ceil(l/2);
  set0(x);
  if Odd(l) then
    x[n] := 2
  else
    x[n] := 6;
  Result := BigInteger.create(x, 1);
end;

function BigInteger.Sqrt: BigInteger;
var
  r: BigInteger;
  x, sqx: number;
begin
  r := SqrtRough;
  x := r.GetAbsoluteValue;
  sqx := Sq(x);
  if cmp(sqx, a) = 0 then begin
    Result := r;
    Exit;
  end;

end;

function BigInteger.SqrtCeil: BigInteger;
var
  b, c: BigInteger;
  zero: number;
begin
  b := BigInteger.Create(1);
  c := BigInteger.Create(0);
  set0(zero);
  repeat
    Substract(b);
    b.Add(BigInteger.Create(2));
    c.biginc;
  until s < 1;
  if cmp(a, zero) = 1 then
    c.bigInc;
  Result := c;
end;

function BigInteger.SqrtFloor: BigInteger;
var
  b, c: BigInteger;
  zero: number;
begin
  b := BigInteger.Create(1);
  c := BigInteger.Create(0);
  set0(zero);
  repeat
    Substract(b);
    b.Add(BigInteger.Create(2));
    c.biginc;
  until s < 1;
  if (s < 0) and (cmp(a, zero) = 1) then
    c.bigDec;
  Result := c;
end;

function BigInteger.SubStract(b: BigInteger): BigInteger;
var
  c: BigInteger;
begin
  c := b.Copy;
  c.InvertSign;
  Result := Add(c);
end;

function BigInteger.toExt: Extended;
begin
  Result := s * toExtended(a);
end;

procedure BigInteger.writeToFile(var f: TextFile);
begin
  showf(f, a);
end;

end.
